﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Graphics;

namespace ScrumSim
{
    class Player : AnimatedGameObject
    {
        protected Vector2 mVelocity;

        protected float     mGravity;
        protected float     mSpeed;

        protected Vector2 mDeltaPosition;

        protected bool mGrounded;
        protected bool mDead;

        protected Rectangle mLastRectGrounded;

        public bool dead { get { return mDead; } }

        public Player(Game1 pGame)
            :base(pGame, "RedRect")
        {
            mVelocity = new Vector2(0, 0);
            mGravity = 500;
            mSpeed = 400;

            AddAnimation("idle", 1.0f, 4, mGame.Content.Load<Texture2D>("idle"), new Rectangle(0, 0, 40, 48));
            AddAnimation("run", 1.0f, 4, mGame.Content.Load<Texture2D>("courir"), new Rectangle(0, 0, 40, 48));
            AddAnimation("jump", 0.5f, 4, mGame.Content.Load<Texture2D>("jump"), new Rectangle(0, 0, 40, 48), false);

            mBoundingBox = new Rectangle(0, 0, 38, 46);

            Play("idle");

            mGrounded = false;
            mDead = false;
        }

        public override void Update(Microsoft.Xna.Framework.GameTime gameTime)
        {
            float lDelta = (float)gameTime.ElapsedGameTime.TotalSeconds;

            if (mGrounded)
                mVelocity.X = 0;
            else
            {
                Play("jump");
                mVelocity.X -= (mVelocity.X * 2) * lDelta;
            }

            HandleInput(lDelta);

            if (Math.Abs(mVelocity.X) > mSpeed)
                mVelocity.X = Math.Sign(mVelocity.X) * mSpeed;

            //if(!mGrounded)
                mVelocity.Y += mGravity * lDelta;

            if (mVelocity.Y > mGravity)
                mVelocity.Y = mGravity;

            Vector2 lLastPos = mPosition;

            mPosition += mVelocity * lDelta;

            if (mPosition.Y + mBoundingBox.Height > mGame.graphics.PreferredBackBufferHeight)
            {//touch bottom of screen
                mDead = true;
            }

            mDeltaPosition = mPosition - lLastPos;

            base.Update(gameTime);
        }

        //---------------------------------------------------------------------------

        private void HandleInput(float pDelta)
        {
            KeyboardState lState = Keyboard.GetState();

            float lFactor = 1.0f;
            if (!mGrounded)
                lFactor = 0.1f;

            if (lState.IsKeyDown(Keys.Left))
            {
                mFlipX = true;

                if(mGrounded)
                    Play("run");
                mVelocity.X -= mSpeed * lFactor;
            }
            else if(lState.IsKeyDown(Keys.Right))
            {
                mFlipX = false;

                if(mGrounded)
                    Play("run");
                mVelocity.X += mSpeed * lFactor;
            }
            else if (mGrounded)
            {
                Play("idle");
            }

            if (lState.IsKeyDown(Keys.Space) && mGrounded)
            {
                Play("jump");
                mVelocity.Y -= mGravity * 0.9f;
                mGrounded = false;
            }
        }

        //----------------------------------------------------------------------------

        public void HandleEnvironnement(LinkedList<GameObject> pEnv, LinkedList<Enemy> pEnnemies)
        {
            if (mDeltaPosition.Length() < 0.0001f)
                return;

            bool mCollisionBottom = false;

            foreach(GameObject plat in pEnv)
            {
                CollisionInfo lInfo = CheckCollision(plat);
                Side lSide = lInfo.mSide;

                if (lSide != Side.NONE)
                {
                    Vector2 lProjected = Vector2.Normalize(mDeltaPosition) * Vector2.Dot(Vector2.Normalize(mDeltaPosition), lInfo.mPenetrationVector);

                    if((lSide & Side.BOTTOM) != 0)
                    {
                        if (Math.Abs(lInfo.mPenetrationVector.Y) < Math.Abs(lInfo.mPenetrationVector.X))
                        {
                            mGrounded = true;
                            mCollisionBottom = true;
                            mPosition.Y = plat.position.Y - mBoundingBox.Height + 1;
                            mVelocity.Y = 0;
                        }
                    }

                    /*if ((lSide & Side.TOP) != 0)
                    {
                        if ((mPosition.Y - mDeltaPosition.Y) > pEnv[i].position.Y + pEnv[i].BBox.Height)
                        {
                            mPosition.Y = pEnv[i].position.Y + pEnv[i].BBox.Height;
                            mVelocity.Y = 0;
                        }
                    }*/

                    if ((lSide & Side.LEFT) != 0)
                    {
                        if (Math.Abs(lInfo.mPenetrationVector.Y) > Math.Abs(lInfo.mPenetrationVector.X))
                        {
                            mPosition.X = plat.position.X + plat.BBox.Width;
                        }
                    }

                    if ((lSide & Side.RIGHT) != 0)
                    {
                        if (Math.Abs(lInfo.mPenetrationVector.Y) > Math.Abs(lInfo.mPenetrationVector.X))
                        {
                            mPosition.X = plat.position.X - mBoundingBox.Width;
                        }
                    }
                }
            }

            if (!mCollisionBottom)
                mGrounded = false;


            //*************ENNEMIES************************//

            foreach (Enemy lEnnemy in pEnnemies)
            {
                if (lEnnemy.dead)
                    continue;

                CollisionInfo lInfo = CheckCollision(lEnnemy);

                if (lInfo.mSide != Side.NONE)
                {
                    if ((lInfo.mSide & Side.BOTTOM) != 0)
                    {
                        if (Math.Abs(lInfo.mPenetrationVector.Y) < Math.Abs(lInfo.mPenetrationVector.X))
                        {
                            mVelocity.Y = -200;
                            lEnnemy.die();
                        }
                        else
                        {
                            mDead = true;
                        }
                    }
                    else
                        mDead = true;
                }
            }
        }


    }
}
